﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Types.Interval;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// If you choose GREEN, all green based pixel will stay all other pixels will be blacked out.
    /// Same goes for other colors
    /// </summary>
    public class RGBFilter2 : BaseForeBackgroundColorFilter
    {
        protected float m_fMinIntensity = -1;
        protected float m_fMinHue = -1;

        protected Colorable m_Colorable = Colorable.None;
        protected ColorDelegate m_ColorDelegate = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="RGBFilter"/> class.
        /// </summary>
        public RGBFilter2()
        {
            m_Colorable = LowLevelGraphics.Colorable.Red;
            InitializeColorabled(m_Colorable);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_colorable"></param>
        public RGBFilter2(Colorable _colorable)
        {
            InitializeColorabled(_colorable);
        }

        /// <summary>
        /// Gets or sets colorable
        /// </summary>
        public Colorable Colorable
        {
            get { return m_Colorable; }
            set 
            {
                m_Colorable = value;
                InitializeColorabled(value);
            }
        }

        protected delegate Color ColorDelegate(Color _color);

        /// <summary>
        /// Initialize Colorable
        /// </summary>
        /// <param name="_colorable"></param>
        private void InitializeColorabled(Colorable _colorable)
        {
            if (_colorable == Colorable.Blue)
            {
                m_ColorDelegate = delegate(Color _color)
                { 
                    return Color.FromArgb(0, 0, ImageMath.Clamp(_color.B - _color.R + (_color.B - _color.G), 0, 255)); 
                };
            }
            else if (_colorable == Colorable.Green)
            {
                m_ColorDelegate = delegate(Color _color) 
                { 
                    return Color.FromArgb(0, ImageMath.Clamp(_color.G - _color.B + (_color.G - _color.R), 0, 255), 0); 
                };
            }
            else if (_colorable == Colorable.Magenta)
            {
                m_ColorDelegate = delegate(Color _color)
                {
                    return Color.FromArgb(ImageMath.Clamp(_color.R - _color.G + (_color.B - _color.G), 0, 255), 0, ImageMath.Clamp(_color.B - _color.R + (_color.R - _color.G), 0, 255));
                };
            }
            else if (_colorable == Colorable.Red)
            {
                m_ColorDelegate = delegate(Color _color)
                { 
                    return Color.FromArgb(ImageMath.Clamp(_color.R - _color.B + (_color.R - _color.G), 0, 255), 0, 0); 
                };
            }
            else if (_colorable == Colorable.Cyan)
            {
                m_ColorDelegate = delegate(Color _color)
                {
                    return Color.FromArgb(0, ImageMath.Clamp(_color.G - _color.B + (_color.B - _color.R), 0, 255), ImageMath.Clamp(_color.B - _color.R + (_color.G - _color.R), 0, 255));
                };
            }
            else if (_colorable == Colorable.Yellow)
            {
                m_ColorDelegate = delegate(Color _color)
                {
                    return Color.FromArgb(ImageMath.Clamp(_color.R - _color.B + (_color.G - _color.B), 0, 255), ImageMath.Clamp(_color.G - _color.B + (_color.R - _color.B), 0, 255), 0);
                };
            }
            else if (_colorable == Colorable.Gray)
            {
                m_ColorDelegate = delegate(Color _color)
                {
                    return Color.FromArgb(ImageMath.Clamp(255 - (_color.R + _color.G + _color.B), 0, 255), ImageMath.Clamp(255 - (_color.R + _color.G + _color.B), 0, 255), ImageMath.Clamp(255 - (_color.R + _color.G + _color.B), 0, 255));
                };
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RGBFilter"/> class.
        /// </summary>
        /// <param name="_rgbFilter">The _RGB filter.</param>
        internal RGBFilter2(RGBFilter2 _rgbFilter)
        {
            m_Colorable = _rgbFilter.m_Colorable;
            this.m_fMinIntensity = _rgbFilter.m_fMinIntensity;
            this.m_fMinHue = _rgbFilter.m_fMinHue;
        }

        /// <summary>
        /// Gets or sets MinIntensity
        /// </summary>
        public float MinIntensity
        {
            get { return m_fMinIntensity; }
            set { m_fMinIntensity = value; }
        }

        /// <summary>
        /// Gets or sets MinHue
        /// </summary>
        public float MinHue
        {
            get { return m_fMinHue; }
            set { m_fMinHue = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;

            Color color = Color.Transparent;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = bitmap.GetPixel(x, y);
                    color = m_ColorDelegate(color);
                    if (color.GetHue() > m_fMinHue && color.GetBrightness() > m_fMinIntensity)
                    {
                        bitmap.SetPixel(x, y, color);
                    }
                    else
                    {
                        bitmap.SetPixel(x, y, m_ColorBackground);
                    }
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new RGBFilter2(this);
        }
    }
}
